#ifndef DOCUMENT_H
#define DOCUMENT_H

#include "pdffile.h"
#include "sessionmanager.h"
#include "extractdialog.h"
#include "externaltools.h"

#include <QObject>
#include <QDebug>
#include <QFileInfo>
#include <QTextDocument>

#include "image.h"

/**
 * @brief The Document class
 */
class Document : public QObject
{
    Q_OBJECT

private:
    Tesseract *m_tesseract;     // instance de Tesseract
    Config* m_config;           // instance de configuration

    Session m_emptySession;

//    QString m_documentPath; // chemin du document sur le disque
    PDFFile m_pdf;          // Poppler
    int m_documentType;         // type de document
    Image m_originalImage;      // image originale
    Image m_rotatedImage;       // image ayant subi la rotation
    Image m_previewImage;       // image de prévisualisation
    SessionManager* m_sessionManager;   // gestionnaire de session
    Session *m_session;                 // la session en cours



    // attributs

    bool m_loadingDocument;


    int m_currentPdfPage;
    int m_firstPdfPage;
    int m_lastPdfPage; // dernier n° de page

    bool restoreStateFrom (Session *session);
    bool saveStateTo (Session *s);

    void updatePreview ();

    // "getters"
    bool isEmpty () const { return fileName ().isEmpty (); }
    QString fileName () { return m_session->fileName (); }
    bool mustCleanImage () { return m_session->mustCleanImage (); }
    QList<QRect> greenRects () { return m_session->greenRects (); }
    QList<QRect> redRects () { return m_session->redRects (); }
    int pdfCurrentPage () { return m_session->pdfCurrentPage (); }
    double scale () { return m_session->scale (); }
    int contrast () { return qRound (100.0 * m_session->contrast () / 255.0); }
    qreal zoom1 () { return m_session->zoom1 (); }
    qreal zoom2 () { return m_session->zoom2 (); }
    int rotation () { return m_session->rotation (); }
    QString text () { return m_session->text (); }

    bool analyzeDocument (const QString &path);

    void exportToWordProcessor ();
    void exportToDicodor ();

    //------------------ UNDO - redo
public slots:
    void undo ();
    void redo ();

private:
    void clearUndo ();
    void clearRedo ();
    void clearUndoAndRedo ();

    bool canUndo ();
    bool canRedo ();
    void prepareUndo ();
    void prepareRedo ();

    void clearSession();
    bool openSession (Session* session);    // utiliser openDocument ()

public:
    explicit Document (SessionManager* sessionManager, QObject *parent);
    ~Document ();
    enum DocumentType { TypeUnknown = -1, TypeImage, TypePdf };
    enum ExtractMode { ModeROC, ModePDF };

    void openLastDocument () { openDocument (m_sessionManager->currentSession ()->fileName ()); }
    void clear ();
    bool isImage () const { return m_documentType == TypeImage; }
    bool isPdf () const { return m_documentType == TypePdf; }
    bool PDFDocContainsText ();
    bool PDFRectContainsText (const QRectF &rect);

    QString rotatedProperties () const { return m_rotatedImage.properties (); }
    QString previewProperties () const { return m_previewImage.properties (); }
    const QString& fileName () const { return m_session->fileName (); }
    int currentPdfPage () const { return m_currentPdfPage; }
    int firstPdfPage () const { return m_firstPdfPage; }
    int lastPdfPage () const { return m_lastPdfPage; }

    const Image &rotatedImage () const { return m_rotatedImage; }
    const QPixmap rotatedPixmap () const { return m_rotatedImage.toPixmap (); }
    const Image &previewImage () const { return m_previewImage; }
    const QPixmap previewPixmap () const { return m_previewImage.toPixmap (); }



signals:
    void empty (const bool b);
    void pathChanged (const QString& documentPath);
    void originalPixmapAvailable (const QPixmap &original);
    void previewPixmapAvailable (const QPixmap &preview);
    void rotationChanged (const int rotation);
    void scaleChanged (const double scale);
    void contrastChanged (const int contrast);
    void optionCleanImageChanged (const bool clean);
    void rectsChanged (QList<QRect> const &redList, QList<QRect> const &greenList);

    void typePdfChanged (const bool b);
    void pageRangeChanged (const int first, const int last);
    void currentPageChanged (const int currentPg);
    void zoom1Changed (const qreal z1);
    void zoom2Changed (const qreal z2);

    void textIsAvailable (); // dans m_text

public slots:
    void onAskInformationsAboutCurrentImage ();

    void setPath (const QString& path);
    void setTypePdf (const bool b);
    void setRectLists (const QList<QRect> &redList, const QList<QRect> &greenList);
    void clearRectList ();
    void setOptionCleanPreview (const bool b);
    void setPDFPageRange(const int first, const int last);
    void setPdfCurrentPage (const int pageNum);

    void setScale (const double s);
    void setContrastFromGUI (const int c);
    void setOptionCleanImage (const bool b);

    void setRotationRight ();
    void setRotationLeft ();
    void setDocumentType (const int type);
    void setAbsoluteRotation (const int angle);
    void onTextExtractionRequired ();
    void onTextExtractionRequired (const QRectF &rect);
    void onOCRRequired ();
    void onROIOCRRequired (ImagePart *);
    void onTextIsAvailable();
    void setText (const QString& text);
    void onZoomed1 (qreal z) {
        m_session->setZoom1 (z);
        updatePreview ();
    }
    void onZoomed2 (qreal z) {
        m_session->setZoom2 (z);
        updatePreview ();
    }

    bool openDocument(const QString &path);
private slots:
    void onEndOfOCR (const QStringList &resultNames);
};


#endif // DOCUMENT_H
